package modelo;

import java.util.ArrayList;
import modelo.edificios.EdificioComercial;
import modelo.edificios.EdificioIndustrial;
import modelo.edificios.EdificioResidencial;
import modelo.mapa.Mapa;

public class CalculadorDeFelicidad {
        
    private ArrayList<EdificioResidencial> edificiosResidenciales;
    private ArrayList<EdificioComercial> edificiosComerciales;
    private ArrayList<EdificioIndustrial> edificiosIndustriales;

    public int calcularPorcentajeDeFelicidad(ArrayList<EdificioComercial> listadoDeEdificiosComerciales, ArrayList<EdificioIndustrial> listadoDeEdificiosIndustriales, 
                    ArrayList<EdificioResidencial> listadoDeEdificiosResidenciales) 
    {
        this.edificiosResidenciales = listadoDeEdificiosResidenciales;
        this.edificiosComerciales = listadoDeEdificiosComerciales;
        this.edificiosIndustriales = listadoDeEdificiosIndustriales;
        int cantidadDeCiudadanos = 0;
        for(EdificioResidencial edificioResidencial : this.edificiosResidenciales)
        {
        	cantidadDeCiudadanos += edificioResidencial.obtenerCantidadDePersonasQueSeAlojanEnEdificio();
        }
        int porcentajeTotalDeFelicidad = 0;
        int porcentajeFelicidadPorCercania = this.calcularFelicidadPorCercanias();
        int porcentajeFelicidadPorServicios = this.calcularFelicidadServicios();
        int porcentajeFelicidadPorTrabajo = 0;
        if (cantidadDeCiudadanos > 0)
        {
            porcentajeFelicidadPorTrabajo = (int)((this.obtenerCapacidadDeTrabajo(listadoDeEdificiosIndustriales)*100)/(cantidadDeCiudadanos*0.25));
            if (porcentajeFelicidadPorTrabajo > 100)
            {
            	porcentajeFelicidadPorTrabajo = 100;
            }
        }                       
        if(porcentajeFelicidadPorServicios == 0)
        {
           	porcentajeTotalDeFelicidad = 0;
        }
        else
        {
    		porcentajeTotalDeFelicidad = (int)((porcentajeFelicidadPorCercania + porcentajeFelicidadPorServicios + porcentajeFelicidadPorTrabajo)/3);
        }
        return porcentajeTotalDeFelicidad;
    }
    
    private int calcularFelicidadPorCercanias() 
    {
        int felicidad = 0;      
        for (EdificioResidencial edificioResidencial : this.edificiosResidenciales)
        {
            felicidad += this.calcularFelicidad(edificioResidencial,this.edificiosComerciales);
            felicidad += this.calcularFelicidad(this.edificiosIndustriales,edificioResidencial);
        }
        int cantidadEdificiosResidenciales = this.edificiosResidenciales.size();
        if (cantidadEdificiosResidenciales > 0)
        {
        	return (int) (felicidad*100/(2*cantidadEdificiosResidenciales));
        }
        return 0;       
    }

    private int calcularFelicidad(EdificioResidencial edificioResidencial, ArrayList<EdificioComercial> listadoDeEdificiosComerciales)
    {
        double distanciaDiagonal = Mapa.getInstance().getDistanciaDiagonal();
        double distanciaParcialEntreEdificios;
        
        for (EdificioComercial edificioComercial : listadoDeEdificiosComerciales)
        {
            if(Mapa.getInstance().estanConectados(edificioResidencial.obtenerUbicacion(), edificioComercial.obtenerUbicacion()))
            {
                distanciaParcialEntreEdificios = edificioResidencial.obtenerUbicacion().getDistancia(edificioComercial.obtenerUbicacion());
                if(distanciaParcialEntreEdificios < (distanciaDiagonal/4))
                {
                	return 1;
                }
            }
        }
        return 0;               
    }
    
    private int calcularFelicidad(ArrayList<EdificioIndustrial> listadoDeEdificiosIndustriales,EdificioResidencial edificioResidencial)
    {
        double distanciaDiagonal = Mapa.getInstance().getDistanciaDiagonal();
        double distanciaMinimaEntreDosEdificios = distanciaDiagonal;
        double distanciaParcialEntreEdificios;

        for (EdificioIndustrial edificioIndustrial : listadoDeEdificiosIndustriales)
        {
	        if(Mapa.getInstance().estanConectados(edificioResidencial.obtenerUbicacion(), edificioIndustrial.obtenerUbicacion()))
	        {
                distanciaParcialEntreEdificios = edificioResidencial.obtenerUbicacion().getDistancia(edificioIndustrial.obtenerUbicacion());
                if(distanciaParcialEntreEdificios < distanciaMinimaEntreDosEdificios)
                {
                	distanciaMinimaEntreDosEdificios = distanciaParcialEntreEdificios;
                }
	        }
        }
        if( ( distanciaMinimaEntreDosEdificios > (distanciaDiagonal/3)) && (distanciaMinimaEntreDosEdificios < ((distanciaDiagonal*2)/3)) )                     
        {
        	return 1;
        }
        return 0;
    }

    private int calcularFelicidadServicios()
    {
        int cantidadDeEdificiosConServicios = 0;

        for (EdificioResidencial edificioResidencial : this.edificiosResidenciales)
        {
            cantidadDeEdificiosConServicios += this.calcularFelicidadPorServicios(edificioResidencial);
        }
        if(this.edificiosResidenciales.size() > 0)
        {
            return (int)((cantidadDeEdificiosConServicios*100)/(this.edificiosResidenciales.size() ));
        }
        return 0;
    }
            
    private int calcularFelicidadPorServicios(EdificioResidencial edificioResidencial)
    {
	    boolean conectadoConComercial = false;
	    boolean conectadoConIndustrial = false;         
	    if(edificioResidencial.tieneServicios())
	    {
            conectadoConComercial = false;
            for (EdificioComercial edificioComercial : this.edificiosComerciales)
            {
                if(!conectadoConComercial)
                {
                    conectadoConComercial = Mapa.getInstance().estanConectados(edificioResidencial.obtenerUbicacion(), edificioComercial.obtenerUbicacion());
                }
                    
            }
            if (conectadoConComercial)
            {
                conectadoConIndustrial = false;
                for (EdificioIndustrial edificioIndustrial : this.edificiosIndustriales)
                {
                    if(!conectadoConIndustrial)
                    {
                    	conectadoConIndustrial = Mapa.getInstance().estanConectados(edificioResidencial.obtenerUbicacion(), edificioIndustrial.obtenerUbicacion());
                    }                                               
                }
            }                               
	    }
	    if((conectadoConIndustrial)&&(conectadoConComercial))
	    {
	    	return 1;
	    }
	    return 0;
    }

    public int obtenerCapacidadDeTrabajo(ArrayList<EdificioIndustrial> listadoDeEdificiosIndustriales) 
    {       
        int capacidadTrabajoTotal = 0;
        int edificiosIndustrialesConServicios = 0;
        for (EdificioIndustrial edificioIndustrial : listadoDeEdificiosIndustriales)
        {
            if ( edificioIndustrial.tieneServicios())
            {
            	edificiosIndustrialesConServicios++;
            }
            capacidadTrabajoTotal = edificioIndustrial.obtenerCapacidadAlojamiento();
        }
        return (edificiosIndustrialesConServicios*capacidadTrabajoTotal);
    }
}
